home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / GENSIG.C < prev    next >
C/C++ Source or Header  |  1991-08-23  |  16KB  |  385 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       Program:    gensig.c             24 July 1991                */
  3. /*       Author:     Andrew H. Derbyshire                             */
  4. /*       Address:    ahd@kew.com                                      */
  5. /*       Function:   Append a random quote to an electronic           */
  6. /*                   mail signature file                              */
  7. /*       Language:   Borland C++ 2.0 (in ANSI C mode)                 */
  8. /*       Arguments:  Name of file with fixed text input               */
  9. /*                   Name of file with variable quotes                */
  10. /*                   Name of file to be written                       */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <io.h>
  16. #include <dir.h>
  17. #include <sys/stat.h>
  18. #include <string.h>
  19. #include <time.h>
  20.  
  21. #include "timestmp.h"
  22.  
  23. /*--------------------------------------------------------------------*/
  24. /*                    Internal function prototypes                    */
  25. /*--------------------------------------------------------------------*/
  26.  
  27. static void usage( void );
  28.  
  29. static long chooseit( struct stat *current_status,
  30.                  const char *lookaside,
  31.                  const char *fname );
  32.  
  33. static long getquote( const char *data);
  34.  
  35. static void CopyQuote( const char *fname, long where, FILE *stream);
  36.  
  37. static void CopyFixed( const char *fname, FILE *stream );
  38.  
  39. /*--------------------------------------------------------------------*/
  40. /*    m a i n                                                         */
  41. /*                                                                    */
  42. /*    main program                                                    */
  43. /*--------------------------------------------------------------------*/
  44.  
  45. void main( int argc, char **argv)
  46. {
  47.  
  48.     long where;
  49.     FILE *stream;
  50.  
  51.     banner( argv );
  52.  
  53. /*--------------------------------------------------------------------*/
  54. /*                  Validate the number of arguments                  */
  55. /*--------------------------------------------------------------------*/
  56.  
  57.       if ( argc !=  4 )
  58.          usage();
  59.  
  60. /*--------------------------------------------------------------------*/
  61. /*    Determine the number of the quotes available, and then          */
  62. /*    select one                                                      */
  63. /*--------------------------------------------------------------------*/
  64.  
  65.       where = getquote( argv[2] );
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*                      Open up our output file                       */
  69. /*--------------------------------------------------------------------*/
  70.  
  71.       stream = fopen( argv[3] , "w");
  72.       if ( stream == NULL )
  73.       {
  74.          perror( argv[3] );
  75.          exit(1);
  76.       }
  77.  
  78. /*--------------------------------------------------------------------*/
  79. /*           Copy the fixed and variable parts of the file            */
  80. /*--------------------------------------------------------------------*/
  81.  
  82.       CopyFixed( argv[1], stream );
  83.       CopyQuote( argv[2], where, stream );
  84.  
  85. /*--------------------------------------------------------------------*/
  86. /*                   Close up and return to caller                    */
  87. /*--------------------------------------------------------------------*/
  88.  
  89.       fclose( stream );
  90.       exit( 0 );
  91.  
  92. } /* main */
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*    u s a g e                                                       */
  96. /*                                                                    */
  97. /*    Report program usage and then exit                              */
  98. /*--------------------------------------------------------------------*/
  99.  
  100. static void usage( void )
  101. {
  102.    printf("Usage:\tgensig\taddr-file quote-file output-file\n");
  103.    printf("\taddr-file\tFixed portion of signature file\n");
  104.    printf("\tquote-file\tFile of quotes, separated by delimiter lines\n");
  105.    printf("\toutput-file\tOutput file with fixed portion and single quote\n");
  106.    exit( 2 );
  107. } /* usage */
  108.  
  109. /*--------------------------------------------------------------------*/
  110. /*    g e t q u o t e                                                 */
  111. /*                                                                    */
  112. /*    Select a quote to process                                       */
  113. /*--------------------------------------------------------------------*/
  114.  
  115. static long getquote( const char *data)
  116. {
  117.    struct stat current_status;
  118.    long where;
  119.  
  120.    char lookaside[FILENAME_MAX];
  121.    char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*       Get size and data information on the quotes data file        */
  125. /*--------------------------------------------------------------------*/
  126.  
  127.    if(stat((char *) data, ¤t_status ) <0)
  128.    {
  129.       perror( data );         /* If no data file, panic gracefully   */
  130.       exit( 3 );
  131.    } /* if */
  132.  
  133. /*--------------------------------------------------------------------*/
  134. /*       Build the lookaside file name from the data file name        */
  135. /*--------------------------------------------------------------------*/
  136.  
  137.    fnsplit( data, drive, dir, file, ext);
  138.    fnmerge( lookaside, drive, dir, file, ".las");
  139.  
  140. /*--------------------------------------------------------------------*/
  141. /*    Now get the location of the quote; if it fails the first        */
  142. /*    time, then the lookaside buffer is updated and we can try       */
  143. /*    again                                                           */
  144. /*--------------------------------------------------------------------*/
  145.  
  146.    where = chooseit( ¤t_status, lookaside, data );
  147.    if  (where == -1 )
  148.    {
  149.       where = chooseit( ¤t_status, lookaside, data );
  150.       if ( where == - 1)
  151.       {
  152.          printf("Unable to create lookaside file \"%s\"!\n",
  153.                   lookaside );
  154.          exit( 4 );
  155.       } /* if ( where == - 1) */
  156.    } /* if ( where == - 1) */
  157.  
  158. /*--------------------------------------------------------------------*/
  159. /*                          Return to caller                          */
  160. /*--------------------------------------------------------------------*/
  161.  
  162.    return where;
  163.  
  164. } /* getquote */
  165.  
  166. /*--------------------------------------------------------------------*/
  167. /*    c h o o s e i t                                                 */
  168. /*                                                                    */
  169. /*    Returns number of quotes in file                                */
  170. /*--------------------------------------------------------------------*/
  171.  
  172. static long chooseit( struct stat *current_status,
  173.                  const char *lookaside,
  174.                  const char *fname )
  175. {
  176.    FILE *stream;
  177.    FILE *data;
  178.    long where;
  179.    int quotes = 0;
  180.    int quote;
  181.  
  182.    char buf[BUFSIZ];
  183.    char delimiter[BUFSIZ];
  184.  
  185. /*--------------------------------------------------------------------*/
  186. /*    Open up the lookaside file and determine if it is up to         */
  187. /*    date.  If so, choose an entry and return it.                    */
  188. /*--------------------------------------------------------------------*/
  189.  
  190.    stream = fopen( lookaside , "rb" );
  191.    if ( stream != NULL )
  192.    {
  193.       struct stat status;
  194.       fread( &status, sizeof status, 1, stream);
  195.       if ((status.st_size == current_status->st_size) &&
  196.           (status.st_mtime == current_status->st_mtime))
  197.       {                       /* Lookaside file up to date, use it   */
  198.          if( stat((char *) lookaside, &status ) < 0)
  199.          {
  200.             perror( lookaside );
  201.             exit( 5 );
  202.          } /* if */
  203.             quotes = (status.st_size - sizeof status) / sizeof where;
  204.                               /* Determine number of quote pointers
  205.                                  in lookaside file from the file's
  206.                                  length                              */
  207.          randomize();         /* Roll them bones ...                 */
  208.          quote  = random( quotes );
  209.                               /* ... Lucky seven?                    */
  210.          fseek( stream, quote * sizeof where , SEEK_CUR );
  211.                               /* Step required number of quotes
  212.                                  into the file                       */
  213.          fread( &where, sizeof where, 1, stream);
  214.                               /* Read offset in data file of quote   */
  215.          printf("Chose quote %d of %d starting at byte %ld of file %s:\n\n",
  216.                   quote + 1 , quotes, where, fname);
  217.                               /* Announce number of quote of the day */
  218.          fclose( stream );    /* Done with lookaside file, of course */
  219.          return where;        /* Return position in file to caller   */
  220.       } /* if */
  221.       else
  222.          fclose( stream );
  223.    } /* if ( stream != NULL ) */
  224.    else
  225.       perror( lookaside );
  226.  
  227. /*--------------------------------------------------------------------*/
  228. /*               We have to rewrite the lookaside file                */
  229. /*--------------------------------------------------------------------*/
  230.  
  231.    data   = fopen( fname, "rt");          /* Open data file to scan  */
  232.    if ( data == NULL )                    /* Did it open?            */
  233.    {
  234.       perror( fname );                    /* No --> Error            */
  235.       exit( 6 );
  236.    }
  237.    stream = fopen( lookaside , "wb" );    /* Open lookaside file     */
  238.    if ( stream == NULL )                  /* Did it open?            */
  239.    {
  240.       perror( lookaside );                /* No --> Error            */
  241.       exit( 7 );
  242.    }
  243.  
  244. /*--------------------------------------------------------------------*/
  245. /*    Start the new lookaside file with the status of the data        */
  246. /*    file for later comparisons                                      */
  247. /*--------------------------------------------------------------------*/
  248.  
  249.    fwrite( current_status, sizeof *current_status, 1, stream);
  250.  
  251. /*--------------------------------------------------------------------*/
  252. /*    Get the first line of the file, which will contain the          */
  253. /*    delimiter line                                                  */
  254. /*--------------------------------------------------------------------*/
  255.  
  256.    fgets(delimiter, BUFSIZ, data );
  257.    where = ftell( data );  /* Get location of possible first quote   */
  258.  
  259. /*--------------------------------------------------------------------*/
  260. /*                  Now process the rest of the file                  */
  261. /*--------------------------------------------------------------------*/
  262.  
  263.    while( fgets(buf, BUFSIZ, data ) != NULL )
  264.    {
  265.       if ( strcmp( buf, delimiter ))   /* Delimiter line?            */
  266.       {                                /* No --> data line           */
  267.          if ( where != -1L )  /* First line of new quote?            */
  268.          {                    /* Yes --> Write location to lookaside */
  269.             quotes ++ ;
  270.             fwrite( &where, sizeof where, 1, stream);
  271.             where = -1L;
  272.          } /* if */
  273.       } /* if */
  274.       else
  275.          where = ftell( data );        /* Delimiter line, remember
  276.                                           location of NEXT line in
  277.                                           file                       */
  278.    } /* while */
  279.  
  280. /*--------------------------------------------------------------------*/
  281. /*                 Close up shop and return to caller                 */
  282. /*--------------------------------------------------------------------*/
  283.  
  284.    fclose( stream );
  285.    fclose( data );
  286.  
  287.    if ( quotes == 1 )
  288.    {
  289.       printf("Invalid data file; first line not a delimiter line!");
  290.       exit( 99 );
  291.    }
  292.  
  293.     printf("Updated lookaside file %s with %d quotes.\n",
  294.                lookaside , quotes);
  295.  
  296.    return -1;                 /* Inform caller that lookaside
  297.                                  file was updated                    */
  298. } /* chooseit */
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*    C o p y F i x e d                                               */
  302. /*                                                                    */
  303. /*    Copy fixed input text (user name and address) to output file    */
  304. /*--------------------------------------------------------------------*/
  305.  
  306. static void CopyFixed( const char *fname, FILE *stream )
  307. {
  308.    FILE *input;
  309.    char buf[BUFSIZ];
  310.  
  311. /*--------------------------------------------------------------------*/
  312. /*                    Open input file for copying                     */
  313. /*--------------------------------------------------------------------*/
  314.  
  315.    input = fopen( fname, "r");
  316.    if ( input == NULL )
  317.    {
  318.       perror( fname );
  319.       exit ( 8 );
  320.    }
  321.  
  322. /*--------------------------------------------------------------------*/
  323. /*             Copy the fixed input to the signature file             */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.    while( fgets( buf, BUFSIZ, input ) != NULL)
  327.       fputs( buf, stream );
  328.  
  329. /*--------------------------------------------------------------------*/
  330. /*                 Close up shop and return to caller                 */
  331. /*--------------------------------------------------------------------*/
  332.  
  333.    fclose( input );
  334. } /* CopyFixed */
  335.  
  336. /*--------------------------------------------------------------------*/
  337. /*    C o p y Q u o t e                                               */
  338. /*                                                                    */
  339. /*    Write a quote to the output file                                */
  340. /*--------------------------------------------------------------------*/
  341.  
  342. static void CopyQuote( const char *fname, long where, FILE *stream)
  343. {
  344.    FILE *input;
  345.    char buf[BUFSIZ];
  346.    char delimiter[BUFSIZ];
  347.  
  348. /*--------------------------------------------------------------------*/
  349. /*         Open up the quotes file and get the delimiter line         */
  350. /*--------------------------------------------------------------------*/
  351.  
  352.    input = fopen( fname, "r");
  353.    if ( input == NULL )
  354.    {
  355.       perror( fname );
  356.       exit ( 9 );
  357.    }
  358.  
  359.    fgets(delimiter, BUFSIZ, input );
  360.  
  361. /*--------------------------------------------------------------------*/
  362. /*   Position to the beginning of the actual quote to be processed    */
  363. /*--------------------------------------------------------------------*/
  364.  
  365.    fseek( input, where , SEEK_SET );
  366.  
  367. /*--------------------------------------------------------------------*/
  368. /*      Copy the quote to both the signature file and the screen      */
  369. /*--------------------------------------------------------------------*/
  370.  
  371.    while( fgets( buf, BUFSIZ, input ) != NULL)
  372.    {
  373.       if (!strcmp( delimiter, buf ))   /* Delimiter line?            */
  374.          break;                        /* Yes --> End of quote       */
  375.       fputs( buf, stream );   /* Copy quote to signature file        */
  376.       fputs( buf, stdout );   /* Copy quote to screen                */
  377.    } /* while( fgets( buf, BUFSIZ, input ) != NULL) */
  378.  
  379. /*--------------------------------------------------------------------*/
  380. /*                 Close up shop and return to caller                 */
  381. /*--------------------------------------------------------------------*/
  382.  
  383.    fclose( input );
  384. } /* CopyQuote */
  385.